package com.zdp.middleware.whitelist;

import ch.qos.logback.core.joran.util.beans.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.zdp.middleware.whitelist.annotation.DoWhiteList;
import org.apache.commons.beanutils.BeanUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * 切面，处理 白名单注解
 * @author ZhengDp
 * @Date 2023/5/26 18:40
 */
// 声明切面
@Aspect
public class DoJoinPoint {

    private Logger logger = LoggerFactory.getLogger(DoJoinPoint.class);

    @Resource
    private String whiteListConfig;

    // 定义切面表达式 ==> 要切的位置 ==> 切点
    @Pointcut("@annotation(com.zdp.middleware.whitelist.annotation.DoWhiteList)")
    public void aopPoint() {
    }

    // 定义环绕切面
    @Around("aopPoint()")
    public Object doRouter(ProceedingJoinPoint jp) throws Throwable {
        Method method = getMethod(jp);
        // 获取注解
        DoWhiteList whiteList = method.getAnnotation(DoWhiteList.class);
        // 从方法入参中提取 属性值
        String keyValue = getFieldValue(whiteList.key(),jp.getArgs());
        logger.info("middleware whitelist handle method : {} value : {}",method.getName(),keyValue);
        // 放行
        if(null == keyValue || "".equals(keyValue)) {
            return jp.proceed();
        }

        // 白名单用户
        String[] split = whiteListConfig.split(",");

        for(String str : split) {
            if(keyValue.equals(str)) {
                return jp.proceed();
            }
        }
        return returnObject(whiteList,method);
    }

    // 请求被拦截，需要返回 注解中的信息
    private Object returnObject(DoWhiteList whiteList, Method method) throws InstantiationException, IllegalAccessException {
        Class<?> returnType = method.getReturnType();
        String returnJson = whiteList.returnJson();
        if("".equals(returnJson)) {
            return returnType.newInstance();
        }
        return JSON.parseObject(returnJson,returnType);
    }

    private String getFieldValue(String field,Object[] args) {
        String fieldValue = null;
        for(Object arg : args) {
            try {
                if(null == fieldValue || "".equals(fieldValue)) {
                    fieldValue = BeanUtils.getProperty(arg,field);
                } else {
                    break;
                }
            } catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
                if(args.length == 1) {
                    return args[0].toString();
                }
            }
        }
        return fieldValue;
    }

    /*
    * 获取切点的方法
    * */
    private Method getMethod(ProceedingJoinPoint jp) throws NoSuchMethodException {
        // 获取方法签名信息
        Signature signature = jp.getSignature();
        MethodSignature methodSignature = (MethodSignature) signature;
        // 通过方法签名信息确定对应的Method对象并返回
        return jp.getTarget().getClass().getMethod(methodSignature.getName(),methodSignature.getParameterTypes());
    }

}
